package at.horario.web.pages;

import at.horario.model.*;
import at.horario.service.ClasseManager;
import at.horario.service.GenericManager;
import at.horario.service.HorarioManager;
import at.horario.web.component.FieldComponentFeedbackPanel;
import at.horario.web.component.TooltipField;
import static org.apache.commons.lang.StringUtils.EMPTY;
import static org.apache.commons.lang.StringUtils.isEmpty;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Page;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.form.AjaxFormValidatingBehavior;
import org.apache.wicket.authorization.strategies.role.annotations.AuthorizeInstantiation;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.*;
import org.apache.wicket.markup.html.panel.EmptyPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.*;
import org.apache.wicket.spring.injection.annot.SpringBean;
import static org.apache.wicket.util.string.interpolator.MapVariableInterpolator.interpolate;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@AuthorizeInstantiation({"horarioform", "admin"})
public class HorarioForm extends PageTemplate {
    @SpringBean(name = "horarioManager")
    private HorarioManager horarioManager;
    @SpringBean(name = "cicloManager")
    private GenericManager<Ciclo, Integer> cicloManager;
    @SpringBean(name = "classeManager")
    private ClasseManager classeManager;

    private final Page backPage;

    Map<String, Object> classeGrupo;


    /**
     * Constructor user to create a new user
     *
     * @param backPage page to navigate to after this page completes its work
     */
    public HorarioForm(Page backPage) {
        this(backPage, new Model(new Horario()));
    }

    public HorarioForm() {
        this(new Index(), new Model(new Horario()));
    }


    /**
     * Constructor used to edit an model
     *
     * @param backPage page to navigate to after this page completes its work
     * @param model    model to edit
     */
    public HorarioForm(final Page backPage, IModel model) {
        this.backPage = backPage;

        // Create and add the form
        EditForm form = new EditForm("horario-form", model) {
            protected void onSave(Horario horario, Map<String, Object> classeGrupo) {
                onSaveHorario(horario, classeGrupo);
            }

            protected void onCancel() {
                onCancelEditing();
            }

            protected void onDelete(Horario user) {
                onDeleteUser(user);
            }
        };
        add(form);
    }


    /**
     * Listener method for save action
     *
     * @param horario horario bean
     */
    protected void onSaveHorario(Horario horario, Map<String, Object> classeGrupo) {
        log.info("HorarioForm.onSaveHorario");
        horarioManager.save(horario, classeGrupo);

        Map<String, String> params = new HashMap<String, String>();
        params.put("id", horario.getId().toString());
        params.put("descricao", horario.getDescricao());
        String message = interpolate(getLocalizer().getString("horario.saved", this), params);
        System.out.println(message);
        getSession().info(message);

        setRedirect(true);
        setResponsePage(backPage);
    }

    /**
     * Listener method for delete action
     *
     * @param user user bean
     */
    protected void onDeleteUser(Horario user) {
//        userManager.remove(user.getId());
//
//        String message = MapVariableInterpolator.interpolate(getLocalizer().getString("user.deleted", this),
//                new MicroMap("name", user.getFullName()));
//        getSession().info(message);
//
//        backPage.get("feedback").setVisible(true);
//        setRedirect(true);
//        setResponsePage(backPage);
    }

    /**
     * Lister method for cancel action
     */
    private void onCancelEditing() {
        setResponsePage(backPage);
    }


    private abstract class EditForm extends BaseForm {


        private void addField(final FormComponent fc) {
            final String key = "horario." + fc.getId();
            final ResourceModel model = new ResourceModel(key);
            add(fc, model);
            final Label label = new Label(fc.getId() + "label", getLocalizer().getString(key, HorarioForm.this) + "<span class=\"req\">*</span>");
            label.setEscapeModelStrings(false);
            add(label);
            fc.setOutputMarkupId(true);
            label.add(new AttributeModifier("for", true, new AbstractReadOnlyModel() {
                public Object getObject() {
                    return fc.getMarkupId();
                }
            }));
        }


        /**
         * Constructor
         *
         * @param id      component id
         * @param horario User object that will be used as a form bean
         */
        public EditForm(String id, IModel model) {
            /*
             * We wrap the horario bean with a CompoundPropertyModel, this allows
             * us to easily connect form components to the bean properties
             * (component id is used as the property expression)
             */

            super(id, new CompoundPropertyModel(model));


            List<Ciclo> cicloList = getCicloList();

            final DropDownChoice ciclo = new DropDownChoice("ciclo", cicloList);
            ciclo.setRequired(true);

            DropDownChoice turno = new DropDownChoice("turno", Arrays.asList(Turno.values()));
            turno.setRequired(true);


            TextField descricao = new TextField("descricao");
            descricao.setRequired(true);

            addField(ciclo);
            addField(turno);
            addField(descricao);

            final Horario horario = (Horario) model.getObject();

            final Panel cicloPanel;
            if (horario.getCiclo() == null) {
                cicloPanel = new EmptyPanel("cicloPanel");
            } else {
                final Ciclo cc = cicloManager.get(horario.getCiclo().getCicloId());
                if (cc.getCicloId() == 1) {
                    cicloPanel = new CicloIPanel("cicloPanel", horario, cc);
                } else {
                    cicloPanel = new CicloIIPanel("cicloPanel", horario, cc);
                }
            }
            add(cicloPanel);


            ciclo.add(new AjaxFormComponentUpdatingBehavior("onchange") {
                protected void onUpdate(AjaxRequestTarget target) {
                    Ciclo c = (Ciclo) ciclo.getModelObject();

                    CicloPanel cicloPanel;
                    final Ciclo cc = cicloManager.get(c.getCicloId());
                    if (c.getCicloId() == 1) {
                        cicloPanel = new CicloIPanel("cicloPanel", horario, cc);
                    } else {
                        cicloPanel = new CicloIIPanel("cicloPanel", horario, cc);
                    }

                    addOrReplace(cicloPanel);
                    target.addComponent(cicloPanel);

//                    for (int i = 0; i < cicloViews.length; i++) {
//                        RepeatingView cicloView = cicloViews[i];
//
//                        if (c.getCicloId() == (i + 1))
//                            cicloView.setVisible(true);
//                        else
//                            cicloView.setVisible(false);
//                    }
                    target.addComponent(EditForm.this);
                }
            });


            AjaxFormValidatingBehavior.addToAllFormComponents(this, "onblur", org.apache.wicket.util.time.Duration.ONE_SECOND);


            add(new Button("save", new Model("Save")) {
                public void onSubmit() {
                    onSave((Horario) getForm().getModelObject(), classeGrupo);
                }
            });

            Button delete = new Button("delete", new Model("Delete")) {
                public void onSubmit() {
                    onDelete((Horario) getForm().getModelObject());
                }
            };

//            if (horario.getId() == null) {
//                delete.setVisible(false);
//                delete.setEnabled(false);
//            }
            add(delete);

            /*
             * Notice the setDefaultFormProcessing(false) call at the end. This
             * tells wicket that when this button is pressed it should not
             * perform any form processing (ie bind request values to the bean).
             */
            add(new Button("cancel", new Model("Cancel")) {
                public void onSubmit() {
                    onCancel();
                }
            }.setDefaultFormProcessing(false));

        }

        /**
         * Callback for cancel button
         */
        protected abstract void onCancel();

        /**
         * Callback for delete button
         *
         * @param user user bean
         */
        protected abstract void onDelete(Horario user);

        /**
         * Callback for save button
         *
         * @param user user bean
         */
        protected abstract void onSave(Horario user, Map<String, Object> classeGrupo);
    }

    private List getCicloList() {
        return cicloManager.getAll();
    }


    public class CicloIPanel extends CicloPanel {

        public CicloIPanel(String s, Horario horario, Ciclo c) {
            super(s, horario, c);
        }
    }

    public class CicloIIPanel extends CicloPanel {

        public CicloIIPanel(String s, Horario horario, Ciclo c) {
            super(s, horario, c);
        }
    }


    /**
     * Created by IntelliJ IDEA.
     * User: AT
     * Date: Feb 17, 2008
     * Time: 2:32:12 AM
     * To change this template use File | Settings | File Templates.
     */
    public abstract class CicloPanel extends Panel {


        public CicloPanel(String s, Horario horario, Ciclo c) {
            super(s);
            init(horario, c);
            setOutputMarkupId(true);
            setOutputMarkupPlaceholderTag(true);
        }

        private Map<String, Object> fillClasseGrupo(Horario horario) {
            Map<String, Object> map = new HashMap<String, Object>();
            if (horario.getId() != null) {
                horario.getHorarioClasseGrupos();
                for (HorarioClasseGrupo h : horario.getHorarioClasseGrupos()) {
                    String classegrupo = "classe" + h.getClasse().getClasseId() + h.getGrupo().getGrupoNome();
                    map.put(classegrupo, h.getNumTurmas());
                }
            }
            return map;
        }

        protected void init(Horario horario, Ciclo c) {
            classeGrupo = fillClasseGrupo(horario);

            for (Classe classe : c.getClasses()) {
                int g = 0;
                for (Grupo grupo : classe.getGrupos()) {
                    String classegrupo = "classe" + classe.getClasseId() + grupo.getGrupoNome();
                    final String key = "horario." + classegrupo;
                    final String message = getLocalizer().getString(key, HorarioForm.this);
                    final Label label = new Label(classegrupo + "label", message + (isEmpty(message) ? EMPTY : "<span class=\"req\">*</span>"));
                    label.setEscapeModelStrings(false);
                    add(label);
                    final RequiredTextField textField = new RequiredTextField(classegrupo, new ClasseGrupoModel(classegrupo));

                    final FieldComponentFeedbackPanel fieldComponent = new FieldComponentFeedbackPanel(classegrupo + "-feedback", textField);
                    fieldComponent.setOutputMarkupId(true);
                    fieldComponent.setOutputMarkupPlaceholderTag(true);
                    add(fieldComponent);
                    add(new TooltipField("_" + classegrupo) {

                        public boolean isLabelVisible() {
                            return ((BaseForm) this.getForm()).isShowtooltiplabel();
                        }
                    });
                    add(textField);
                }
            }


        }

        private class ClasseGrupoModel implements IModel {
            String name;

            private ClasseGrupoModel(String name) {
                this.name = name;
            }

            public Object getObject() {
                return classeGrupo.get(name);
            }

            public void setObject(Object object) {
                classeGrupo.put(name, object);
            }

            public void detach() {

            }
        }
    }
}